/*************************************************************************
 * Nuvoton Technology Corporation confidential
 *
 * Copyright (c) 2009 by Nuvoton Technology Corporation
 * All rights reserved
 * 
 * FILENAME
 *     IdePIOCommand.c
 *
 * VERSION
 *     1.0
 *
 * DESCRIPTION
 *     ATAPI disk PIO commands
 *
 * HISTORY
 *     2008.06.25		Created
 *
 * REMARK
 *     None
 **************************************************************************/
#ifdef ECOS
#include "stdio.h"
#include "stdlib.h"
#include "drv_api.h"
#else
#include <stdio.h>
#include <string.h>
#endif

#include "AtapiReg.h"
#include "Atapi.h"  

/******************************************************************
 *  Name : __swap16
 *
 *  Description	: swap the order of the	bytes in a 16-bit word
 *
 *  Input  : unsigned 16-bit word
 *
 *  Output : unsigned swaped 16-bit word
 *******************************************************************/
void __swap16(USHORT *value)
{
    USHORT temp;
  
    temp = *value	& 0x00ff;
    temp <<= 8;
    *value = (*value >> 8) | temp;
} 
//------------------------------------------------------------------------
//  Transfer the logical sector(LBA) to physical Cylinder, Head and Sector (CHS)
//
//  In : drive_no : selected drive
//        LBA : starting logical sector address
//
//  Out: _HD_HEAD, _HD_CYLH, _HD_CYLL, _HD_SEC : CHS mode
//------------------------------------------------------------------------
void atapiTransferLBAtoCHS(UCHAR drive_no, UINT32 startLBA, 
            USHORT *_HD_HEAD, USHORT *_HD_CYLH, USHORT *_HD_CYLL, USHORT *_HD_SEC)
{
    USHORT   cylinder, head, sector;
    
    sector    = (USHORT)	(startLBA  % IDE_HEADER_INFO[drive_no].sectors ) + 1;
    head      = (USHORT)	(startLBA  / IDE_HEADER_INFO[drive_no].sectors );
    cylinder  = (USHORT)	( head / IDE_HEADER_INFO[drive_no].heads );
    head     %= IDE_HEADER_INFO[drive_no].heads;
    
    *_HD_CYLH  = (UCHAR) ((cylinder & 0xff00) >> 8);
    *_HD_CYLL  = (UCHAR) (cylinder & 0x00ff);
    *_HD_HEAD  = (UCHAR) (head & 0x0f);
    *_HD_SEC   = (UCHAR) (sector & 0x00ff);
} 
//------------------------------------------------------------------------
//  Read the HD information from the specified drive. (PIO Data In state)
//
//  Input  : Drive number (0 or 1)
//
//  Output : global var : struct  IDE_HEADER_INFO
//
//  Return : 0 : HD not found 
//               1 : Success
//------------------------------------------------------------------------
int atapiReadHDInfo(USHORT drive_no)
{
    USHORT i, data;
    UCHAR  *buf, ch;	
	
	if (!atapi_wait_BSY())	    // wait BSY=0 & DRQ=0
        return 0;
    if (!atapi_wait_DRQ(0))
        return 0;
	
    ide_outp(ATAPI_ATA_DEVH, (drive_no ? SLAVE_MODE : MASTER_MODE));

    // here delay or not ?       
    ide_outp(ATAPI_ATA_COMD, IDENTIFY_DRV);   // write command code
        
    if( !atapi_wait_INTRQ())
   	{
   		sysprintf("wait INTRQ error !!\n");	 
	 	return 0;
   	}
   	
    _atapi_INTRQ = FALSE;        
  
    // wait for data ready (BSY=0 & DRQ=1)
    if (!atapi_wait_BSY() )	    // wait command completed
        return 0;
    if (!atapi_wait_DRQ(1))		//wait data ready
    {
    	sysprintf("wait DQR(1) error !!\n");	 
        return 0;
    }
        
    // Read data from drive buffer. 256 words = 512 bytes 
    buf = (UCHAR *) &IDE_HEADER_INFO[drive_no];
    for (i=0; i<256; i++)
    {
        data = ide_inphw(ATAPI_ATA_DATA);
#ifdef __BIG_ENDIAN	       
	    *(buf)   = (UCHAR) ( (data >> 8) & 0x00ff );
	    *(buf+1) = (UCHAR) (	data & 0x00ff );
	    buf += 2;
#else
        *buf++ = (UCHAR) (data & 0x00FF);
        *buf++ = (UCHAR) ((data >> 8) & 0x00FF);
#endif	                  
    }
 
#ifndef __BIG_ENDIAN
    for (i=0; i<40; i+=2)
    {
        ch = IDE_HEADER_INFO[drive_no].model_num[i];
        IDE_HEADER_INFO[drive_no].model_num[i]   = IDE_HEADER_INFO[drive_no].model_num[i+1];
        IDE_HEADER_INFO[drive_no].model_num[i+1] = ch;
    }
    
    for (i=0; i<8; i+=2)
    {
        ch = IDE_HEADER_INFO[drive_no].firware_rev[i];
        IDE_HEADER_INFO[drive_no].firware_rev[i]   = IDE_HEADER_INFO[drive_no].firware_rev[i+1];
        IDE_HEADER_INFO[drive_no].firware_rev[i+1] = ch;
    }
    
    for (i=0; i<20; i+=2)
    {
        ch = IDE_HEADER_INFO[drive_no].ser_no[i];
        IDE_HEADER_INFO[drive_no].ser_no[i]   = IDE_HEADER_INFO[drive_no].ser_no[i+1];
        IDE_HEADER_INFO[drive_no].ser_no[i+1] = ch;  
    }
#endif
 
    if (!atapi_wait_BSY())  
        return 0;
  
    return 1;
  
} /* end atapiReadHDInfo */

//------------------------------------------------------------------------
#ifdef DMA_IO

int __ide_swap_buffer(UCHAR count, UCHAR *buf)
{
    int i, j;
    volatile UCHAR *p, *q, tt;
    
    p = buf, q = buf+1;
    UART_printf("buf = %x, p = %x, q=%x\n", buf, p, q);
    
    for (i=0; i<count; i++)
    {
        for (j=0; j<256; j++)
        {
            tt = *p;
            *p = *q;
            *q = tt;
            p+=2;
            q+=2;       
        }
    }
}
#endif

//------------------------------------------------------------------------
//  Set the number of sectors per block
//
//  In : uNumberOfSec :  Sectors/block (<= HD max sectors per block)
//
//  Out: 0 : fail
//          1 : success
//------------------------------------------------------------------------
int atapiSetMultiple(UCHAR drive_no, UCHAR uNumberOfSec)
{
    UINT32 param;
 
    // wait BSY=0 & DRQ=0 
    // prepare  parameter 
    if (!atapi_wait_BSY())
    {
    	sysprintf("wait BSY error !!\n");	 
	 	return 0;
	}
	 
    if (!atapi_wait_DRQ(0))
    {
    	sysprintf("wait DQR error !!\n");	 
        return 0;
    }

    ide_outp(ATAPI_ATA_SEC, uNumberOfSec);    
    ide_outp(ATAPI_ATA_DEVH, (drive_no ? SLAVE_MODE : MASTER_MODE) | LBA_MODE);
    
    // write command code
    /* make sure the output is OK */
    /*if (!atapi_wait_BSY())	 
	{
    	sysprintf("wait BSY error !!\n");	 
	 	return 0;
	}*/
   
    ide_outp(ATAPI_ATA_COMD, SET_MULTIPLE);
   	
   	
   	/* Wait for INTRQ = Assert */    
   	if( !atapi_wait_INTRQ())
   	{
   		sysprintf("wait INTRQ error !!\n");	 
	 	return 0;
   	}
   	_atapi_INTRQ = FALSE;
   	
   	/* make sure the output is OK */
    if (!atapi_wait_BSY())	 
	{
    	sysprintf("wait BSY error !!\n");	 
	 	return 0;
	}	
	
    // check HD's status
    param = ide_inp(ATAPI_ATA_STAT);
    //sysprintf("ATAPI status register [%x]!!\n", param & 0xff);	
    if ( (param & 0xE9) != 0x40 )     
    {
    	sysprintf("{FAIL}ATAPI status register [%x]!!\n", param & 0xff);	 
    	param = ide_inp(ATAPI_ATA_ERR);
    	sysprintf("{FAIL}ATAPI error register [%x]!!\n", param & 0xff);	 
	 	return 0;
	}   

    /* make sure the output is OK */
    /*if (!atapi_wait_BSY())	 
	{
    	sysprintf("wait BSY error !!\n");	 
	 	return 0;
	}*/
    
    return 1;
} 
//------------------------------------------------------------------------
//  Read data sectors from HD
//
//  In : start_sector : starting sector address
//	     sector_num : the number of sectors to be transferred (1-256), (0: 256 sectors)
//
//  Out: buf : get data from HD
//
//  Ret: 0 : fail
//         1 : success
//------------------------------------------------------------------------
int atapiReadSector(UCHAR drive_no, UINT32 start_sector, UCHAR sector_num, UCHAR *buf)
{
    UCHAR param;
    USHORT i, loop, data;
    USHORT _HD_HEAD, _HD_SEC, _HD_CYLH, _HD_CYLL;
	
    if (!atapi_wait_BSY())	    // wait BSY=0 & DRQ=0
        return 0;
    if (!atapi_wait_DRQ(0))
        return 0;

    if (IDE_HEADER_INFO[drive_no].capability & 0x0200)  // LBA Mode 
    {
        ide_outp(ATAPI_ATA_SEC, sector_num);    
        ide_outp(ATAPI_ATA_LBAL, (start_sector & 0x000000FF)); 
        ide_outp(ATAPI_ATA_LBAM, ((start_sector & 0x0000FF00) >> 8));         
        ide_outp(ATAPI_ATA_LBAH, ((start_sector & 0x00FF0000) >> 16));
        ide_outp(ATAPI_ATA_DEVH, ((drive_no ? SLAVE_MODE : MASTER_MODE) 
			        | LBA_MODE | ((start_sector & 0x0F000000) >> 24)));
    }
    else  // CHS Mode
    {
         // Transfer Cylinder, Head, Sector number
        atapiTransferLBAtoCHS(drive_no, start_sector, &_HD_HEAD, &_HD_CYLH, &_HD_CYLL, &_HD_SEC);
   
        ide_outp(ATAPI_ATA_SEC, sector_num);    
        ide_outp(ATAPI_ATA_LBAL, _HD_SEC); 
        ide_outp(ATAPI_ATA_LBAM, _HD_CYLL);         
        ide_outp(ATAPI_ATA_LBAH, _HD_CYLH);
        ide_outp(ATAPI_ATA_DEVH, ((drive_no ? SLAVE_MODE : MASTER_MODE) | _HD_HEAD));
   }
	
    ide_outp(ATAPI_ATA_COMD, READ_SEC);
   
#ifdef DMA_IO
    //GDMA_SRCB0 = (ATAPI_BASE_ADDRRESS+ATAPI_ATA_DATA);
    //GDMA_DSTB0	= (unsigned int)buf;
    //GDMA_TCNT0 = 256;
    //GDMA_CTL0 = 0x10081881;
#endif
 
    /* Reading datas */
    for (loop = 0; loop < sector_num; loop++)
    {
        //UART_printf("[1] loop %d --> GDMACTL0 =%x\n", loop, GDMA_CTL0);

        /* Wait for INTRQ = Assert */    
        if (!atapi_wait_INTRQ())
             return 0;
        _atapi_INTRQ = FALSE;
    
        // wait for data ready (BSY=0 & DRQ=1)
        if (!atapi_wait_BSY() )	    // wait command completed
             return 0;
        if (!atapi_wait_DRQ(1))    // wait data ready
             return 0;
		
#ifdef DMA_IO
        GDMA_SRCB0 = (ATAPI_BASE_ADDRRESS+ATAPI_ATA_DATA);
        GDMA_DSTB0 = (int)(buf + loop * 512);
        GDMA_TCNT0 = 256;
        GDMA_CTL0  = 0x10011881;
        
        while (!(GDMA_CTL0 & 0x00040000) ) 
        {
#ifdef _debug
            //UART_printf(".");
#endif      
            ;
        }
        //GDMA_CTL0  &= ~(0x00040000);      
        //UART_printf("[2] loop %d --> GDMACTL0 =%x, GDMA_TCNT0 = %x\n", loop, GDMA_CTL0, GDMA_TCNT0);      
#else
        /* Read a sector of datas (512 bytes) */
        for (i=0; i<256; i++)
        { 
            data = ide_inphw(ATAPI_ATA_DATA);
            //#ifdef __BIG_ENDIAN	       
            //	       *(buf)   = (UCHAR) ( (data >> 8) & 0x00ff );
            //	       *(buf+1) = (UCHAR) (	data & 0x00ff );
            //	       buf += 2;
            //#else
            *buf++ = (UCHAR) (data & 0x00FF);
            *buf++ = (UCHAR) ((data >> 8) &0x00FF);
            //#endif	       
        }
#endif
        /* Check HD's status. If ERR bit = 1, return FALSE. */
        param = ide_inp(ATAPI_ATA_STAT);
        if (param & 0x01)     
            return 0;
    } /* end loop	*/

    /* make sure the input id OK */
    if (!atapi_wait_BSY()) 
        return 0;
   
#ifdef DMA_IO
#ifdef __BIG_ENDIAN
    // __ide_swap_buffer(count, buf);
#endif
#endif
 
    return 1;

} /* end atapiReadSector */

//------------------------------------------------------------------------
//  Read data sectors from HD
//
//  In : start_sector : starting sector address
//	     sector_num : the number of sectors to be transferred (1-256), (0: 256 sectors)
//
//  Out: buf : get data from HD
//
//  Ret: 0 : fail
//         1 : success
//------------------------------------------------------------------------
int atapiReadMultiple(UCHAR drive_no, UINT32 start_sector, UCHAR sector_num, UCHAR *buf)
{
    UCHAR param;
    USHORT data;
    int i, j, div, NoOfSectorsToBeTransfered;
    UINT32 uNoOfSectorsPerInterrupt, uRemainder;
    USHORT _HD_HEAD, _HD_SEC, _HD_CYLH, _HD_CYLL;

    /*
    if (!atapi_wait_BSY())	    // wait BSY=0 & DRQ=0
        return 0;
    if (!atapi_wait_DRQ(0))
        return 0;
	*/
	
    if (IDE_HEADER_INFO[drive_no].capability & 0x0200)  // LBA Mode 
    {
        ide_outp(ATAPI_ATA_SEC, sector_num);    
        ide_outp(ATAPI_ATA_LBAL, (start_sector & 0x000000FF)); 
        ide_outp(ATAPI_ATA_LBAM, ((start_sector & 0x0000FF00) >> 8));         
        ide_outp(ATAPI_ATA_LBAH, ((start_sector & 0x00FF0000) >> 16));
        ide_outp(ATAPI_ATA_DEVH, ((drive_no ? SLAVE_MODE : MASTER_MODE)
		                 | LBA_MODE | ((start_sector & 0x0F000000) >> 24)));
    }
    else  //  CHS Mode 
    {
        // Transfer Cylinder, Head, Sector number
        atapiTransferLBAtoCHS(drive_no, start_sector, &_HD_HEAD, &_HD_CYLH, &_HD_CYLL, &_HD_SEC);
		
        ide_outp(ATAPI_ATA_SEC, sector_num);    
        ide_outp(ATAPI_ATA_LBAL, _HD_SEC); 
        ide_outp(ATAPI_ATA_LBAM, _HD_CYLL);         
        ide_outp(ATAPI_ATA_LBAH, _HD_CYLH);
        ide_outp(ATAPI_ATA_DEVH, ((drive_no ? SLAVE_MODE : MASTER_MODE) | _HD_HEAD));
    }
   
    //write command
    ide_outp(ATAPI_ATA_COMD, READ_MULTIPLE);

    uNoOfSectorsPerInterrupt = IDE_HEADER_INFO[drive_no].current_max_sector_no & 0x0fff;

    do
    {
        div = sector_num / uNoOfSectorsPerInterrupt;
        uRemainder = sector_num % uNoOfSectorsPerInterrupt;

        if(div > 0)
            NoOfSectorsToBeTransfered = uNoOfSectorsPerInterrupt;
        else
            NoOfSectorsToBeTransfered = uRemainder;    

        // Wait for INTRQ = Assert
        if (!atapi_wait_INTRQ())
	        return 0;	
        _atapi_INTRQ = FALSE;
            
        for(i = 0; i < NoOfSectorsToBeTransfered; i++)
        {
            // wait for data ready (BSY=0 & DRQ=1)
           if (!atapi_wait_BSY() )	    // wait command completed
                return 0;
           if (!atapi_wait_DRQ(1))    // wait data ready
                return 0;
     
            for(j = 0; j < 256; j++)     // read a sector (512 bytes)
            {
                data = ide_inphw(ATAPI_ATA_DATA);
                *buf++ = (UCHAR) (data & 0x00FF);
                *buf++ = (UCHAR) ((data >> 8) &0x00FF);
            }    

            /* check HD's status */
            param = ide_inp(ATAPI_ATA_STAT);
            if (param & 0x01)
                return 0;
        }
        
        sector_num -= NoOfSectorsToBeTransfered;        
        if (!sector_num)    // transfer completely
            break;    
    } while (1);

    // make sure the input id OK
    /*
    if (!atapi_wait_BSY())  
        return 0;
    */
   
#ifdef DMA_IO
#ifdef __BIG_ENDIAN
    // __ide_swap_buffer(count, buf);
#endif
#endif
    return 1;

} /* end atapiReadMultiple */

//------------------------------------------------------------------------
//  Write	sectors of datas into HD. 
//
//  Input  : UINT32 initial sector number,
//	     UCHAR  count of sectors,
//	     a data pointer of the data	buffer
//
//  Ret: 0 : fail
//         1 : success
//------------------------------------------------------------------------
int atapiWriteSector(UCHAR drive_no, UINT32 start_sector, UCHAR sector_num, UCHAR *buf)
{
    UINT32 param;
    USHORT *data;
    int loop, i;
    USHORT _HD_HEAD, _HD_SEC, _HD_CYLH, _HD_CYLL;
 
    if (!atapi_wait_BSY())	    // wait BSY=0 & DRQ=0
        return 0;
    if (!atapi_wait_DRQ(0))
        return 0;
 
    if (IDE_HEADER_INFO[drive_no].capability & 0x0200)  // LBA Mode 
    {
        // prepare  parameter
        if (!atapi_wait_BSY())
	      return 0;
   
        ide_outp(ATAPI_ATA_SEC, sector_num);    
        ide_outp(ATAPI_ATA_LBAL, (start_sector & 0x000000FF)); 
        ide_outp(ATAPI_ATA_LBAM, ((start_sector & 0x0000FF00) >> 8));         
        ide_outp(ATAPI_ATA_LBAH, ((start_sector & 0x00FF0000) >> 16));
        ide_outp(ATAPI_ATA_DEVH, ((drive_no ? SLAVE_MODE : MASTER_MODE) | LBA_MODE | ((start_sector & 0x0F000000) >> 24)));
    }
    else // CHS Mode
    {
        // transfer Cylinder, Head, Sector number
        atapiTransferLBAtoCHS(drive_no, start_sector, &_HD_HEAD, &_HD_CYLH, &_HD_CYLL, &_HD_SEC);
   
        /* prepare  parameter */
        if (!atapi_wait_BSY())
	      return 0;
   
        ide_outp(ATAPI_ATA_SEC, sector_num);
        ide_outp(ATAPI_ATA_LBAL, _HD_SEC);
        ide_outp(ATAPI_ATA_LBAM, _HD_CYLL);
        ide_outp(ATAPI_ATA_LBAH, _HD_CYLH);
        ide_outp(ATAPI_ATA_DEVH, ((drive_no ? SLAVE_MODE : MASTER_MODE) | _HD_HEAD));
    }
   
    ide_outp(ATAPI_ATA_COMD, WRITE_SEC);
   
    /* writting datas */
    data =	(USHORT	*) buf;
 
    for (loop=0; loop<sector_num; loop++)
    {
            // wait for data ready (BSY=0 & DRQ=1)
           if (!atapi_wait_BSY() )	    // wait command completed
               return 0;
           if (!atapi_wait_DRQ(1))    // wait data ready
               return 0;

        /* write a sector	of datas */
#ifdef __BIG_ENDIAN
        for (i=0; i<256; i++)
        {          
            temp = ((*data & 0xFF) << 8) | ((*data & 0xFF00) >> 8);
            //__swap16(data);
            ide_outphw(ATAPI_ATA_DATA, (UINT32)temp);
            data++;
        }
#else      
        for(i=0; i<256; i++)
	        ide_outphw(ATAPI_ATA_DATA, (UINT32)(*data++));
#endif

         /* Wait for INTRQ = Assert */    
        if (!atapi_wait_INTRQ())
            return 0;
        _atapi_INTRQ = FALSE;

        /* check HD's status */
        param = ide_inp(ATAPI_ATA_STAT);
        if (param & 0x01)  
            return 0;
    } /* end loop	*/

    /* make sure the output is OK */
    if (!atapi_wait_BSY())
        return 0;
	
    return 1;
} /* end atapiWriteSector */

//------------------------------------------------------------------------
//  Write	data sectors into HD
//
//  In : start_sector : starting sector address
//	     sector_num : the number of sectors to be transferred (1-256), (0: 256 sectors)
//         buf : data buffer for writing
//
//  Ret: 0 : fail
//         1 : success
//------------------------------------------------------------------------
int atapiWriteMultiple(UCHAR drive_no, UINT32 start_sector, UCHAR sector_num, UCHAR *buf)
{
    UINT32 param;
    USHORT *data;
    UINT32  uNoOfSectorsPerInterrupt, uRemainder;
    int i, j, div, NoOfSectorsToBeTransfered;
    USHORT _HD_HEAD, _HD_SEC, _HD_CYLH, _HD_CYLL;

    if (!atapi_wait_BSY())	    // wait BSY=0 & DRQ=0
    {
    	sysprintf("atapi_wait_BSY() error ...\n");
        return 0;
    }
    
    if (!atapi_wait_DRQ(0))
    {
    	sysprintf("atapi_wait_DRQ(0) error ...\n");
        return 0;
    }

    if (IDE_HEADER_INFO[drive_no].capability & 0x0200)  // LBA Mode 
    {
        ide_outp(ATAPI_ATA_SEC, sector_num);    
        ide_outp(ATAPI_ATA_LBAL, (start_sector & 0x000000FF)); 
        ide_outp(ATAPI_ATA_LBAM, ((start_sector & 0x0000FF00) >> 8));         
        ide_outp(ATAPI_ATA_LBAH, ((start_sector & 0x00FF0000) >> 16));
        ide_outp(ATAPI_ATA_DEVH, ((drive_no ? SLAVE_MODE : MASTER_MODE) | LBA_MODE | ((start_sector & 0x0F000000) >> 24)));
    }
    else // CHS Mode 
    {   
        // transfer Cylinder, Head, Sector number
        atapiTransferLBAtoCHS(drive_no, start_sector, &_HD_HEAD, &_HD_CYLH, &_HD_CYLL, &_HD_SEC);
		
        ide_outp(ATAPI_ATA_SEC, sector_num);
        ide_outp(ATAPI_ATA_LBAL, _HD_SEC);
        ide_outp(ATAPI_ATA_LBAM, _HD_CYLL);
        ide_outp(ATAPI_ATA_LBAH, _HD_CYLH);
        ide_outp(ATAPI_ATA_DEVH, ((drive_no ? SLAVE_MODE : MASTER_MODE) | _HD_HEAD));
    }
    
    ide_outp(ATAPI_ATA_COMD, WRITE_MULTIPLE);
   
    // writting data
    data =	(USHORT	*) buf;

    uNoOfSectorsPerInterrupt = IDE_HEADER_INFO[drive_no].current_max_sector_no & 0x0fff;
    
    do
    {
        div = sector_num / uNoOfSectorsPerInterrupt;
        uRemainder = sector_num % uNoOfSectorsPerInterrupt;

        if(div > 0)
            NoOfSectorsToBeTransfered = uNoOfSectorsPerInterrupt;
        else
            NoOfSectorsToBeTransfered = uRemainder;    
           
        for(i = 0; i < NoOfSectorsToBeTransfered; i++)
        {
            // wait for data ready (BSY=0 & DRQ=1)
            if (!atapi_wait_BSY() )	    // wait command completed
            {
		    	sysprintf("atapi_wait_BSY() error ...\n");
		        return 0;
		    }
            if (!atapi_wait_DRQ(1))           // wait data ready
            {
		    	sysprintf("atapi_wait_DRQ(1) error ...\n");
		        return 0;
		    }
        
            for(j = 0; j < 256; j++)
    	        ide_outphw(ATAPI_ATA_DATA, (UINT32)(*data++));

            // check HD's status 
            param = ide_inp(ATAPI_ATA_STAT);
            if (param & 0x01)
            {
            	sysprintf("status error[%x]\n", param);
                return 0;
            }
        }
        
        //sysprintf("atapi_wait_INTRQ(%d) ...\n",uRemainder);
        // Wait for INTRQ = Assert    
        if (!atapi_wait_INTRQ())
        {
	    	sysprintf("atapi_wait_INTRQ(0) error ...\n");
	        return 0;
    	}
        _atapi_INTRQ = FALSE;
        
        sector_num -= NoOfSectorsToBeTransfered;        
        if(!sector_num)    // transfer completely
            break;    
    } while (1);
    

    /* make sure the output is OK */
    if (!atapi_wait_BSY()) 
   // {
    //	sysprintf("atapi_wait_BSY() error ...\n");
        return 0;
    //}
     
    return 1;

} /* end atapiWriteSector */

